#pragma once
#include <iostream>
#include <string>
#include <thread>
#include <vector>
#include <queue>
#include <mutex>
#include<functional>
#include <condition_variable>
namespace Pool
{
    int test_cnt = 0;
    static const unsigned int default_size = std::thread::hardware_concurrency() + 1;
    template <class T>
    class ThreadPool
    {
    private:
        void HandlerTask()
        {
            while (true)
            {
                // 生产者消费者model
                std::unique_lock<std::mutex> lock(_mtx);
                _cond.wait(lock, [this]() {
                        return _tasks.empty() != true || _isrunning == false;
                    });
                //消费
                if(_tasks.empty() && _isrunning == false) break;
                if(_tasks.empty()) continue;
                auto task = _tasks.front();
                _tasks.pop();
                lock.unlock();
                task();
            }
        }
        ThreadPool(int size)
            : _tids(size),
              _size(size),
              _sleep_tids(size),
              _actice_tids(0)
        {
        }
        
    public:
        ~ThreadPool()
        {
            for (auto &tid : _tids)
            {
                if (tid.joinable())
                {
                    tid.join();
                    std::cout << "join !" << std::endl;
                }
            }
        }
        void run()
        {
            _isrunning = true;
            for (int i = 0; i < _size; ++i)
            {
                _tids.push_back(std::thread(std::bind(&ThreadPool::HandlerTask, this)));
                std::cout << "构造线程 : " << i + 1 << std::endl;
            }
        }
        void push(const T &task)
        {
            std::unique_lock<std::mutex> lock(_mtx);
            _tasks.push(task);
        }
        void stop()
        {
             std::unique_lock<std::mutex> lock(_mtx);
             _isrunning = false;
        }
        static ThreadPool<T>* GetInstance(int size = default_size)
        {   
            static ThreadPool<T> _pool(size);
            return &_pool;
        }
    private:
        std::vector<std::thread> _tids;
        std::queue<T> _tasks;
        unsigned int _size;
        unsigned int _sleep_tids;
        unsigned int _actice_tids;
        std::mutex _mtx;
        std::condition_variable _cond;
        bool _isrunning = false;
    };
};
